﻿#include "HybridPointJunctionDialog.h"
#include "ui_HybridPointJunctionDialog.h"

#include "OperatorsInterface/ParaWidgetInterfaceOperator.h"

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKVec3D.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKHybridJunctionPoint.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractFESubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsShellPhysicsProp.h"

#include <QList>
#include <QMessageBox>
#include <QCheckBox>

#define PointJunction_SubSysPos Qt::UserRole
#define PointJunction_PointPos Qt::UserRole+1

namespace GUI
{
    HybridPointJunctionDialog::HybridPointJunctionDialog(int dataID, EventOper::ParaWidgetInterfaceOperator * oper, bool isCreate) :
        GUIJunctionDialogBase(dataID, oper, isCreate, FITKAPP->getGlobalData()->getMainWindow())
    {
        _ui = new Ui::HybridPointJunctionDialog();
        _ui->setupUi(this);

        if (isCreate == false) {
            _currentDataID = dataID;
        }
        //初始化
        this->init();
    }

    HybridPointJunctionDialog::~HybridPointJunctionDialog()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void HybridPointJunctionDialog::init()
    {
        QStringList connectSEAHeader;
        connectSEAHeader << QString(tr("Connected SEA subsystems")) << QString(tr("Radius [m]")) << QString(tr("Ove")) << QString(tr("Alpha [deg]"));
        _ui->tableWidget_SEA->setColumnCount(4);
        _ui->tableWidget_SEA->setHorizontalHeaderLabels(connectSEAHeader);
        //自适应
        _ui->tableWidget_SEA->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        //隐藏行表头
        _ui->tableWidget_SEA->verticalHeader()->setVisible(false);
        _ui->tableWidget_SEA->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);

        QStringList connectFEHeader;
        connectFEHeader << QString(tr("Connected FE subsystems"));
        _ui->tableWidget_FE->setColumnCount(1);
        _ui->tableWidget_FE->setHorizontalHeaderLabels(connectFEHeader);
        //自适应
        _ui->tableWidget_FE->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        //隐藏行表头
        _ui->tableWidget_FE->verticalHeader()->setVisible(false);
        //_ui->tableWidget_FE->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);

        _ui->label_Image->setPixmap(QPixmap(":/icons/SEA_Junction_Point.png"));
        _ui->checkBox_EnabledJunction->setChecked(true);

        if (_isCreate)
        {
            this->InitCreate();
        }
        else
        {
            this->InitEdit();
        }
    }

    void HybridPointJunctionDialog::setSubsysIDs(QList<QPair<int, int>> subsys)
    {
        if (_SEAModel == nullptr || _FEModel == nullptr) return;
        //SEA模型管理器
        Acoustics::FITKAcousticsSEASubSysManager* seaManager = _SEAModel->getSEASubSysManager();
        Acoustics::FITKAcousticsFESubSysManager* feManager = _FEModel->getFESubSysManager();
        if (!seaManager || !feManager) return;
        //遍历所有子系统
        QList<Acoustics::FITKSEAJunPointConStr> connectsSEA = {};
        QList<Acoustics::FITKFEJunPointConStr> connectsFE = {};
        for (QList<QPair<int, int>>::iterator iter = subsys.begin(); iter != subsys.end(); ++iter)
        {
            int subsysID = iter->first, pointID = iter->second;
            Acoustics::FITKAbstractSEASubSys* subSysSEAData = seaManager->getDataByID(subsysID);
            Acoustics::FITKAbstractFESubSys* subSysFEData = feManager->getDataByID(subsysID);
            if (!subSysSEAData && !subSysFEData) continue;
            //判断子系统是否被使用
            bool isUseSub = false;
            for (Acoustics::FITKSEAJunPointConStr str : connectsSEA) {
                if (str._subSysID != subsysID)continue;
                isUseSub = true;
                break;
            }
            for (Acoustics::FITKFEJunPointConStr str : connectsFE) {
                if (str._subSysID != subsysID)continue;
                isUseSub = true;
                break;
            }
            if (isUseSub == true)continue;

            if (subSysSEAData)
            {
                //子系统id与点id
                Acoustics::FITKSEAJunPointConStr conStr;
                conStr._subSysID = subsysID;
                conStr._pointID = pointID;

                Acoustics::FITKAcousticsPhysicsPropManager* physicsManager = _physics->getPhysicsPropManager();
                if (physicsManager == nullptr)continue;
                int physicsId = subSysSEAData->getPropSectionID();

                if (subSysSEAData->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEABeam) {
                    //梁的半径
                    auto physicsData = dynamic_cast<Acoustics::FITKAcousticsAbsShellPhysicsProp*>(physicsManager->getDataByID(physicsId));
                    if (physicsData) {
                        /*conStr._radius = physicsData->getShellThickness();*/
                    }
                }
                else {
                    //板厚度
                    auto physicsData = dynamic_cast<Acoustics::FITKAcousticsAbsShellPhysicsProp*>(physicsManager->getDataByID(physicsId));
                    if (physicsData) {
                        conStr._radius = physicsData->getShellThickness();
                    }
                    //角度
                }

                connectsSEA.append(conStr);
            }
            else if (subSysFEData)
            {
                //子系统id与点id
                Acoustics::FITKFEJunPointConStr conStr;
                conStr._subSysID = subsysID;
                conStr._pointID = pointID;

                connectsFE.append(conStr);
            }
        }
        //初始化
        this->initSEATable(connectsSEA);
        this->initFETable(connectsFE);
    }

    void HybridPointJunctionDialog::setNode(int nodeID)
    {
        this->initWidgetNodeData(nodeID);
    }

    void HybridPointJunctionDialog::on_pushButton_Ok_clicked()
    {
        if (_isCreate) {
            if (OKCreate() == false)return;
        }
        else {
            if (OKEdit() == false)return;
        }
        if (_oper) {
            _oper->setArgs(objID_String, _currentDataID);
            _oper->execProfession();
        }
        this->accept();
    }

    void HybridPointJunctionDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void HybridPointJunctionDialog::InitCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        QString name = "Hybrid Point-0";
        name = _DiscModel->getJunctionManager()->checkName(name);
        _ui->lineEdit_Name->setText(name);
    }

    void HybridPointJunctionDialog::InitEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        Acoustics::FITKHybridJunctionPoint* junData = dynamic_cast<Acoustics::FITKHybridJunctionPoint*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return;
        QString name = junData->getDataObjectName();
        _ui->lineEdit_Name->setText(name);

        setDataToWidget(junData);
    }

    void HybridPointJunctionDialog::initSEATable(QList<Acoustics::FITKSEAJunPointConStr> connection)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr) false;
        _ui->tableWidget_SEA->setRowCount(0);
        int rowIndex = 0;
        for (Acoustics::FITKSEAJunPointConStr str : connection) {
            Acoustics::FITKAbstractSEASubSys* subSys = _SEAModel->getSEASubSysManager()->getDataByID(str._subSysID);
            if (subSys == nullptr)continue;
            Acoustics::FITKAbstractSEASubSys::SEASubSysType type = subSys->getSEASubSysType();
            _ui->tableWidget_SEA->setRowCount(rowIndex + 1);
            QTableWidgetItem* item = new QTableWidgetItem();
            item->setText(subSys->getDataObjectName());
            item->setData(PointJunction_SubSysPos, subSys->getDataObjectID());
            item->setData(PointJunction_PointPos, str._pointID);
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_SEA->setItem(rowIndex, 0, item);

            item = new QTableWidgetItem();
            item->setText(QString::number(str._radius));
            item->setData(PointJunction_SubSysPos, subSys->getDataObjectID());
            item->setData(PointJunction_PointPos, str._pointID);
            if (type == Acoustics::FITKAbstractSEASubSys::SEABeam)item->setFlags(Qt::ItemIsEditable);
            _ui->tableWidget_SEA->setItem(rowIndex, 1, item);

            if (type != Acoustics::FITKAbstractSEASubSys::SEABeam) {
                QCheckBox* checkBox = new QCheckBox(this);
                checkBox->setChecked(str._isAlphaOve);
                checkBox->setProperty("row", rowIndex);
                connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(slotAlphaOveCheck()));
                _ui->tableWidget_SEA->setCellWidget(rowIndex, 2, checkBox);

                /*item = new QTableWidgetItem();
                item->setText(subSys->getDataObjectName());
                item->setData(PointJunction_SubSysPos, subSys->getDataObjectID());
                item->setData(PointJunction_PointPos, str._pointID);
                if (str._isAlphaOve) item->setFlags(Qt::ItemIsEnabled);
                else item->setFlags(Qt::ItemIsEditable);
                _ui->tableWidget_SEA->setItem(rowIndex, 3, item);*/
            }
            rowIndex++;
        }
    }

    void HybridPointJunctionDialog::initFETable(QList<Acoustics::FITKFEJunPointConStr> connection)
    {
        if (_FEModel == nullptr && _FEModel->getFESubSysManager() == nullptr) false;
        _ui->tableWidget_FE->setRowCount(0);
        int rowIndex = 0;
        for (Acoustics::FITKFEJunPointConStr str : connection) {
            Acoustics::FITKAbstractFESubSys* subSys = _FEModel->getFESubSysManager()->getDataByID(str._subSysID);
            if (subSys == nullptr)continue;
            _ui->tableWidget_FE->setRowCount(rowIndex + 1);
            QTableWidgetItem* item = new QTableWidgetItem();
            item->setText(subSys->getDataObjectName());
            item->setData(PointJunction_SubSysPos, subSys->getDataObjectID());
            item->setData(PointJunction_PointPos, str._pointID);
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_FE->setItem(rowIndex, 0, item);

            rowIndex++;
        }
    }

    void HybridPointJunctionDialog::initWidgetNodeData(int pointID)
    {
        if (_DiscModel == nullptr && _DiscModel->getNodes() == nullptr) return;
        //获取数据
        Core::FITKNode* node = _DiscModel->getNodes()->getNodeByID(pointID);
        if (node == nullptr)return;
        double coor[3]{ 0,0,0 };
        node->getCoor(coor);
        //设置数据到界面
        _ui->lineEdit_NodeID->setText(QString::number(pointID));
        _ui->lineEdit_X->setText(QString::number(coor[0]));
        _ui->lineEdit_Y->setText(QString::number(coor[1]));
        _ui->lineEdit_Z->setText(QString::number(coor[2]));
    }

    bool HybridPointJunctionDialog::OKCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        QString name = _ui->lineEdit_Name->text();
        if (_DiscModel->getJunctionManager()->getDataByName(name)) {
            QMessageBox box(QMessageBox::Warning, "", QString(tr("\"%1\" already exists and cannot be overwritten.")).arg(name), QMessageBox::Ok);
            box.exec();
            return false;
        }

        Acoustics::FITKHybridJunctionPoint* junData = new Acoustics::FITKHybridJunctionPoint();
        junData->setDataObjectName(name);
        junData->setAutoCreate(false);
        _currentDataID = junData->getDataObjectID();
        //设置界面数据
        getDataFromWidget(junData);
        _DiscModel->getJunctionManager()->appendDataObj(junData);
        return true;
    }

    bool HybridPointJunctionDialog::OKEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        QString name = _ui->lineEdit_Name->text();
        auto junData = dynamic_cast<Acoustics::FITKHybridJunctionPoint*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return false;
        //名称重复判断
        if (name != junData->getDataObjectName())
            if (_DiscModel->getJunctionManager()->getDataByName(name)) {
                QMessageBox::warning(this, "", tr("\"%1\" already exists and cannot be overwritten.").arg(name), QMessageBox::Ok);
                return false;
            }
        //设置名称
        junData->setDataObjectName(name);
        //设置界面数据
        getDataFromWidget(junData);
        return true;
    }

    void HybridPointJunctionDialog::getDataFromWidget(Acoustics::FITKHybridJunctionPoint* data)
    {
        if (data == nullptr)return;
        QList<Acoustics::FITKSEAJunPointConStr> conInfoSEA;
        QList<Acoustics::FITKFEJunPointConStr> conInfoFE;
        //获取关联SEA子系统数据
        int conRowCount = _ui->tableWidget_SEA->rowCount();
        for (int i = 0; i < conRowCount; i++) {
            Acoustics::FITKSEAJunPointConStr conStr;
            //子系统id与连接点id
            QTableWidgetItem* item = _ui->tableWidget_SEA->item(i, 0);
            if (item) {
                conStr._subSysID = item->data(PointJunction_SubSysPos).toInt();
                conStr._pointID = item->data(PointJunction_PointPos).toInt();
            }
            //厚度
            item = _ui->tableWidget_SEA->item(i, 1);
            if (item) {
                conStr._radius = item->text().toDouble();
            }
            //是否角度可修改
            QCheckBox* checkBox = dynamic_cast<QCheckBox*>(_ui->tableWidget_SEA->cellWidget(i, 2));
            if (checkBox) {
                conStr._isAlphaOve = checkBox->isChecked();
            }
            //角度
            item = _ui->tableWidget_SEA->item(i, 3);
            if (item) {
                conStr._alpha = item->text().toDouble();
            }
            conInfoSEA.append(conStr);
        }
        //获取关联FE子系统数据
        conRowCount = _ui->tableWidget_FE->rowCount();
        for (int i = 0; i < conRowCount; i++) {
            Acoustics::FITKFEJunPointConStr conStr;
            //子系统id与连接点id
            QTableWidgetItem* item = _ui->tableWidget_SEA->item(i, 0);
            if (item) {
                conStr._subSysID = item->data(PointJunction_SubSysPos).toInt();
                conStr._pointID = item->data(PointJunction_PointPos).toInt();
            }
            conInfoFE.append(conStr);
        }
        data->replaceConnections(conInfoSEA, conInfoFE);

        data->setEnabledJunction(_ui->checkBox_EnabledJunction->isChecked());
        int pointID = _ui->lineEdit_NodeID->text().toInt();
        data->setPointID(pointID);
    }

    void HybridPointJunctionDialog::setDataToWidget(Acoustics::FITKHybridJunctionPoint* data)
    {
        bool isEnable = data->getEnabledJunction();
        _ui->checkBox_EnabledJunction->setChecked(isEnable);

        this->initSEATable(data->getSEAConnections());
        this->initFETable(data->getFEConnections());
        this->initWidgetNodeData(data->getPointID());
    }
}
